package MLP
{
	import UIUtils.uif_MLPEncoder;
	import UIUtils.uif_util;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.filters.BlurFilter;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.PerspectiveProjection;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class mlp_layer3d extends Sprite {
		private var _layersRect: Rectangle;
		public function mlp_layer3d() {
			super();
		}
		
		public function addLayers(a_layers: Array, a_depths: Object=0): void {
			var dv			: Number = a_depths as Number;
			var startDepth	: Number = (dv != 0)?(a_layers.length/2 * dv):0;
			_layersRect = new Rectangle(Number.MAX_VALUE, Number.MIN_VALUE, 0, 0);
			var baseDepth	: Number = 10;
			a_layers.forEach(function(a_layer: Object, i: int, arr: Array): void {
				if (a_layer is DisplayObject) {
					if (_layersRect.x > a_layer.x) _layersRect.x = a_layer.x;
					if (_layersRect.y > a_layer.y) _layersRect.y = a_layer.y;
					if (_layersRect.right < a_layer.x + a_layer.width) _layersRect.right = a_layer.x + a_layer.width;
					if (_layersRect.bottom < a_layer.y + a_layer.height) _layersRect.bottom = a_layer.y + a_layer.height;
					
					if (dv) {
						a_layer.z = baseDepth + startDepth;
						startDepth -= dv;
					} else if (a_depths is Array)
						a_layer.z = baseDepth + a_depths[i];
					addChild(a_layer as DisplayObject);
				}
			});
			updateZOrder();	
		}
		
		public function get layersRect(): Rectangle {
			return _layersRect;
		}
		
		public function updateZOrder(): void {
			var depth	: Array = new Array();
			var l_mc	: DisplayObject;
			
			for (var i: int=0; i < numChildren; i++) {
				l_mc = getChildAt(i);
				depth.push({depth: l_mc.z, mc: l_mc});
			}
			depth.sortOn('depth', Array.NUMERIC | Array.DESCENDING);
			for (i=0;i<depth.length;i++) {
				l_mc = getChildAt(i);
				if (l_mc != depth[i].mc) swapChildren(l_mc, depth[i].mc);
			}			
		}		
		
		public function resize(a_size: Point): mlp_layer3d {
			var rect	: Rectangle = uif_util.EnterHere(new Rectangle(0, 0, a_size.x, a_size.y), _layersRect.size);
			var scale	: Point = new Point(rect.width/_layersRect.width, rect.height/_layersRect.height);
			var items	: Array = new Array(); 
			
			for (var i: int=0; i < numChildren; i++) {
				var mat		: Matrix = new Matrix(scale.x, 0, 0, scale.y);
				var child	: DisplayObject = getChildAt(i);
				var item	: DisplayObject;
				var tmat	: Matrix3D = child.transform.matrix3D.clone();
				tmat.appendTranslation(rect.x - child.x + child.x * scale.x, rect.y - child.y + child.y * scale.y, -child.z + child.z * scale.x);
				
				if (child is Bitmap) {
					var bmp		: Bitmap = child as Bitmap;
					var newBmp	: Bitmap;
					if (i == 0) {
						var b_mat: Matrix = mat.clone();
						var b_mat2: Matrix = new Matrix(a_size.x/bmp.bitmapData.width, 0, 0, a_size.y/bmp.bitmapData.height);
						b_mat.translate(tmat.position.x, tmat.position.y);
						newBmp = new Bitmap(new BitmapData(a_size.x, a_size.y, false, 0));
						newBmp.bitmapData.draw(bmp, b_mat2);
						newBmp.bitmapData.applyFilter(newBmp.bitmapData, newBmp.bitmapData.rect, uif_util.NULLPOINT, new BlurFilter(20, 20, 3));
						newBmp.bitmapData.draw(bmp, b_mat);
						tmat.appendTranslation(-tmat.position.x, -tmat.position.y, 0);
					} else {
						newBmp = new Bitmap(new BitmapData(bmp.bitmapData.width * scale.x, bmp.bitmapData.height * scale.y, true, 0));
						newBmp.bitmapData.draw(bmp, mat);
					}
					newBmp.transform.colorTransform = bmp.transform.colorTransform;
					item = newBmp;
				} else if (child as mlp_effectLayer) {
					item = new mlp_effectLayer((child as mlp_effectLayer).params);
					item.width 	= child.width 	* scale.x;
					item.height = child.height	* scale.y;
					(item as mlp_effectLayer).load();
				}
				item.transform.matrix3D = tmat;
				items.push(item);
			}
			var a_image: mlp_layer3d = new mlp_layer3d();
			a_image.addLayers(items);
			a_image._layersRect = new Rectangle(0, 0, a_size.x, a_size.y);
			return a_image;
		}
		
		public function getPreview(a_size: Point): BitmapData {
			var bmd		: BitmapData = new BitmapData(a_size.x, a_size.y);
			var size	: Point 	 = layersRect.size;
			var rect	: Rectangle	 = uif_util.EnterHere(bmd.rect, size); 
			var scale	: Point		= new Point(rect.width/size.x, rect.height/size.y);	
			var mat		: Matrix 	= new Matrix(scale.x, 0, 0, scale.y, rect.x, rect.y);
			var tmpp	: Point		= root.transform.perspectiveProjection.projectionCenter.clone();

			
			root.transform.perspectiveProjection.projectionCenter = new Point(a_size.x, a_size.y);
			bmd.draw(this, mat);
			root.transform.perspectiveProjection.projectionCenter = tmpp;
			return bmd;
		}
		
		public function dispose(): void {
			for (var i: int=0; i < numChildren; i++) {
				var child: DisplayObject = getChildAt(i);
				if (child is Bitmap)
					(child as Bitmap).bitmapData.dispose();
			}
			if (parent) parent.removeChild(this);
		}
	}
}